package com.zshan.clinic.web.service;

import com.alibaba.excel.EasyExcel;
import com.alibaba.excel.ExcelWriter;
import com.alibaba.excel.write.handler.WriteHandler;
import com.alibaba.excel.write.metadata.WriteSheet;
import com.alibaba.excel.write.style.column.LongestMatchColumnWidthStyleStrategy;
import com.zshan.clinic.admin.entity.vo.ClinicRegisterVo;
import com.zshan.clinic.admin.entity.vo.StockOrderPurchasePageVo;
import com.zshan.clinic.admin.service.medical.ClinicRegisterService;
import com.zshan.clinic.admin.service.stock.StockOrderService;
import com.zshan.clinic.common.constant.CommonConstant;
import com.zshan.clinic.common.enums.*;
import com.zshan.clinic.common.exception.BusinessFailException;
import com.zshan.clinic.common.util.decimal.BigDecimalUtils;
import com.zshan.clinic.web.entity.export.OrderPurchaseExport;
import com.zshan.clinic.web.entity.export.RegisterExport;
import com.zshan.clinic.web.handler.FreezeTopRowHandler;
import lombok.extern.slf4j.Slf4j;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Service;
import org.springframework.util.CollectionUtils;

import javax.servlet.http.HttpServletResponse;
import java.io.OutputStream;
import java.math.BigDecimal;
import java.net.URLEncoder;
import java.nio.charset.StandardCharsets;
import java.time.LocalDate;
import java.util.ArrayList;
import java.util.List;


/**
 * 数据导出
 * @author lichen
 */
@Slf4j
@Service
public class ExportService {

    @Autowired
    private ClinicRegisterService clinicRegisterService;

    @Autowired
    private StockOrderService stockOrderService;

    private static final String EXCEL_CONTENT_TYPE = "application/vnd.openxmlformats-officedocument.spreadsheetml.sheet";


    /**
     * 导出挂号列表
     * @param response
     * @param clinicId
     * @param patientName
     * @param deptId
     * @param doctorId
     * @param visitDate
     * @param regStatus
     */
    public void exportRegister(HttpServletResponse response, Long clinicId,String patientName, Long deptId,Long doctorId,LocalDate visitDate,String regStatus) {
        String fileName = "挂号单_" + LocalDate.now() + ".xlsx";
        setDownloadHeader(response, fileName);
        // 自动列宽 + 冻结首行
        WriteHandler autoWidth = new LongestMatchColumnWidthStyleStrategy();
        WriteHandler freezeTop = new FreezeTopRowHandler();
        try (OutputStream os = response.getOutputStream();
             ExcelWriter writer = EasyExcel.write(os, RegisterExport.class)
                     .registerWriteHandler(autoWidth)
                     .registerWriteHandler(freezeTop)
                     .build()) {

            WriteSheet sheet = EasyExcel.writerSheet("挂号列表").build();
            int pageNo = CommonConstant.DEFAULT_1;
            int pageSize = CommonConstant.DEFAULT_1000; //
            boolean hasData = false; // 👈 标记是否有数据写入
            while (true) {
                List<RegisterExport> registerExportList = getRegisterExport(clinicId,patientName,deptId,doctorId,visitDate,regStatus,pageNo,pageSize);
                if (CollectionUtils.isEmpty(registerExportList)) {
                    break;
                }
                writer.write(registerExportList, sheet);
                hasData = true;
                pageNo++;
                // 重要：避免一次性把所有数据查出来
            }
            // 👇 若无数据，仍导出空表头，防止文件损坏
            if (!hasData) {
                writer.write(new ArrayList<RegisterExport>(), sheet);
            }
        } catch (Exception e) {
            log.error("导出失败:{}",e);
            throw new BusinessFailException("网络繁忙，请稍后再试！");
        }
    }

    /**
     * 导出采购单
     * @param response
     * @param clinicId
     * @param orderNo
     * @param orderStatus
     * @param settleStatus
     * @param storageId
     */
    public void exportOrderPurchase(HttpServletResponse response, Long clinicId, String orderNo, String orderStatus, String settleStatus, Long storageId) {
        String fileName = "采购单_" + LocalDate.now() + ".xlsx";
        setDownloadHeader(response, fileName);

        // 自动列宽 + 冻结首行
        WriteHandler autoWidth = new LongestMatchColumnWidthStyleStrategy();
        WriteHandler freezeTop = new FreezeTopRowHandler();

        try (OutputStream os = response.getOutputStream();
             ExcelWriter writer = EasyExcel.write(os, OrderPurchaseExport.class)
                     .registerWriteHandler(autoWidth)
                     .registerWriteHandler(freezeTop)
                     .build()) {

            WriteSheet sheet = EasyExcel.writerSheet("采购列表").build();

            int pageNo = CommonConstant.DEFAULT_1;
            int pageSize = CommonConstant.DEFAULT_1000;
            boolean hasData = false; // 👈 标记是否有数据写入

            while (true) {
                List<OrderPurchaseExport> orderPurchaseExportList = getOrderPurchaseExport(clinicId, orderNo, orderStatus, settleStatus, storageId, pageNo, pageSize);
                if (CollectionUtils.isEmpty(orderPurchaseExportList)) {
                    break;
                }
                writer.write(orderPurchaseExportList, sheet);
                hasData = true;
                pageNo++;
            }
            // 👇 若无数据，仍导出空表头，防止文件损坏
            if (!hasData) {
                writer.write(new ArrayList<OrderPurchaseExport>(), sheet);
            }

        } catch (Exception e) {
            log.error("导出失败:{}", e);
            throw new BusinessFailException("网络繁忙，请稍后再试！");
        }
    }

    /**
     * 查询采购单列表
     * @param clinicId
     * @param orderNo
     * @param orderStatus
     * @param settleStatus
     * @param storageId
     * @param pageNo
     * @param pageSize
     * @return
     */
    public List<OrderPurchaseExport> getOrderPurchaseExport(Long clinicId, String orderNo, String orderStatus, String settleStatus, Long storageId, int pageNo, int pageSize) {
        List<StockOrderPurchasePageVo> orderPurchaseList = stockOrderService.listOrderPurchase(clinicId,orderNo,orderStatus,settleStatus,storageId,pageNo,pageSize);
        if(CollectionUtils.isEmpty(orderPurchaseList)){
            return null;
        }
        List<OrderPurchaseExport> orderPurchaseExportList = new ArrayList<>();
        for(StockOrderPurchasePageVo orderPurchase : orderPurchaseList){
            OrderPurchaseExport orderPurchaseExport = new OrderPurchaseExport();
            orderPurchaseExport.setOrderNo(orderPurchase.getOrderNo());
            orderPurchaseExport.setOrderStatus(PurchaseOrderStatusEnum.getText(orderPurchase.getOrderStatus()));
            orderPurchaseExport.setSettleStatus(SettleStatusEnum.getText(orderPurchase.getSettleStatus()));
            orderPurchaseExport.setInUserName(orderPurchase.getInUserName());
            orderPurchaseExport.setInTime(orderPurchase.getInTime());
            orderPurchaseExport.setSupplyName(orderPurchase.getSupplyName());
            orderPurchaseExport.setManagerName(orderPurchase.getManagerName());
            orderPurchaseExport.setManagerPhone(orderPurchase.getManagerPhone());
            orderPurchaseExport.setStorageName(orderPurchase.getStorageName());
            orderPurchaseExport.setDrugKindCount(orderPurchase.getDrugKindCount());
            orderPurchaseExport.setTotalQty(orderPurchase.getTotalQty());
            orderPurchaseExport.setTotalAmount(BigDecimalUtils.divide(
                    new BigDecimal(orderPurchase.getTotalAmount()),new BigDecimal(CommonConstant.DEFAULT_100),CommonConstant.DEFAULT_2
            ));
            orderPurchaseExport.setRemark(orderPurchase.getRemark());
            orderPurchaseExportList.add(orderPurchaseExport);
        }
        return orderPurchaseExportList;
    }


    /**
     * 查询挂号列表
     * @param clinicId
     * @param patientName
     * @param deptId
     * @param doctorId
     * @param visitDate
     * @param regStatus
     * @param pageNo
     * @param pageSize
     * @return
     */
    public List<RegisterExport> getRegisterExport(Long clinicId,String patientName, Long deptId,Long doctorId,LocalDate visitDate,String regStatus,Integer pageNo, Integer pageSize) {
        List<ClinicRegisterVo> registerVoList = clinicRegisterService.listRegister(clinicId,patientName,deptId,doctorId,visitDate,regStatus,pageNo,pageSize);
        if(CollectionUtils.isEmpty(registerVoList)){
            return null;
        }
        List<RegisterExport> registerExportList = new ArrayList<>();
        for(ClinicRegisterVo clinicRegisterVo : registerVoList){
            RegisterExport registerExport = new RegisterExport();
            registerExport.setVisitNo(clinicRegisterVo.getVisitNo());
            registerExport.setVisitDate(clinicRegisterVo.getVisitDate());
            registerExport.setVisitPeriod(VisitPeriodEnum.getText(clinicRegisterVo.getVisitPeriod()) + clinicRegisterVo.getVisitSeqNo()+"号");
            registerExport.setRegMethod(RegMethodEnum.getText(clinicRegisterVo.getRegMethod()));
            registerExport.setRegChannel(RegChannelEnum.getText(clinicRegisterVo.getRegChannel()));
            registerExport.setDoctorName(clinicRegisterVo.getDoctorName());
            registerExport.setDeptName(clinicRegisterVo.getDeptName());
            registerExport.setVisitType(VisitTypeEnum.getText(clinicRegisterVo.getVisitType()));
            registerExport.setRegType(RegTypeEnum.getText(clinicRegisterVo.getRegType()));
            registerExport.setRegStatus(RegStatusEnum.getText(clinicRegisterVo.getRegStatus()));
            registerExport.setPayStatus(PayStatusEnum.getText(clinicRegisterVo.getPayStatus()));
            registerExport.setPatientName(clinicRegisterVo.getPatientName());
            registerExport.setPatientGender(GenderEnum.getText(clinicRegisterVo.getPatientGender()));
            registerExport.setPatientPhone(clinicRegisterVo.getPatientPhone());
            registerExport.setAge(clinicRegisterVo.getAgeYear()+"岁"+clinicRegisterVo.getAgeMonth()+"月");
            registerExport.setRemark(clinicRegisterVo.getRemark());
            registerExportList.add(registerExport);
        }
        return registerExportList;
    }


    /**
     * 设置 Excel 文件下载响应头
     */
    public static void setDownloadHeader(HttpServletResponse response, String fileName) {
        try {
            // 对文件名进行 URL 编码并处理空格
            String encodedFileName = URLEncoder.encode(fileName, StandardCharsets.UTF_8.name())
                    .replaceAll("\\+", "%20");

            response.setContentType(EXCEL_CONTENT_TYPE);
            response.setCharacterEncoding(StandardCharsets.UTF_8.name());
            response.setHeader("Cache-Control", "no-cache, no-store, must-revalidate");
            response.setHeader("Pragma", "no-cache");
            response.setHeader("Expires", "0");
            response.setHeader("Content-Disposition",
                    String.format("attachment; filename*=UTF-8''%s", encodedFileName));

        } catch (Exception e) {
            throw new IllegalStateException("设置下载 Header 失败", e);
        }
    }

}
